home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1995 October / EnigmA AMIGA RUN 01 (1995)(G.R. Edizioni)(IT)[!][issue 1995-10][Aminet 7].iso / Tools / Useful / AmiCDROM / src / rock.c < prev    next >
C/C++ Source or Header  |  1994-11-03  |  9KB  |  335 lines

  1. /* rock.c:
  2.  *
  3.  * Support for the Rock Ridge filing system.
  4.  *
  5.  * ----------------------------------------------------------------------
  6.  * This code is (C) Copyright 1993,1994 by Frank Munkert.
  7.  * All rights reserved.
  8.  * This software may be freely distributed and redistributed for
  9.  * non-commercial purposes, provided this notice is included.
  10.  * ----------------------------------------------------------------------
  11.  * History:
  12.  * 
  13.  * 05-Feb-94   fmu   Added support for relocated directories.
  14.  * 16-Oct-93   fmu   Adapted to new VOLUME structure.
  15.  */
  16.  
  17. #include <stdlib.h>
  18. #include <string.h>
  19.  
  20. #include <exec/memory.h>
  21.  
  22. #include <clib/exec_protos.h>
  23.  
  24. #ifdef LATTICE
  25. #include <pragmas/exec_pragmas.h>
  26. #endif
  27.  
  28. #include "rock.h"
  29.  
  30. #define VOL(vol,tag) (((t_iso_vol_info *)(vol->vol_info))->tag)
  31. #define OBJ(obj,tag) (((t_iso_obj_info *)(obj->obj_info))->tag)
  32.  
  33. /* Check whether the given volume uses the Rock Ridge Interchange Protocol.
  34.  * The protocol is identified by the sequence
  35.  *            'S' 'P' 7 1 0xbe 0xef
  36.  * in the system use field of the (00) directory in the root directory of
  37.  * the volume.
  38.  *
  39.  * Returns 1 iff the RR protocol is used; 0 otherwise.
  40.  * If the RR protocol is used, *p_skip will be set to the skip length
  41.  * specified in the SP system use field.
  42.  */
  43.  
  44. t_bool Uses_Rock_Ridge_Protocol (VOLUME *p_volume, int *p_skip)
  45. {
  46.   unsigned long loc = VOL(p_volume,pvd).root.extent_loc_m;
  47.   directory_record *dir;
  48.   int system_use_pos;
  49.   unsigned char *sys;
  50.  
  51.   if (!(dir = Get_Directory_Record (p_volume, loc, 0)))
  52.     return 0;
  53.   
  54.   system_use_pos = 33 + dir->file_id_length;
  55.   if (system_use_pos & 1)
  56.     system_use_pos++;
  57.  
  58.   if (system_use_pos >= dir->length)
  59.     return 0;
  60.  
  61.   sys = (unsigned char *) dir + system_use_pos;
  62.   if (sys[0] == 'S' && sys[1] == 'P' && sys[2] == 7 &&
  63.       sys[3] == 1 && sys[4] == 0xbe && sys[5] == 0xef) {
  64.     *p_skip = sys[6];
  65.     return 1;
  66.   } else
  67.     return 0;
  68. }
  69.  
  70. /* Searches for the system use field with name p_name in the directory record
  71.  * p_dir and fills the buffer p_buf (with length p_buf_len) with the information
  72.  * contained in the system use field.
  73.  *
  74.  * p_index is the ordinal number of the system use field (if more than one
  75.  * system use field with the same name is recorded.) 0=first occurrence,
  76.  * 1=second occurrence, and so on.
  77.  *
  78.  * 1 is returned if the system use field has been found; otherwise 0
  79.  * is returned.
  80.  */
  81.  
  82. int Get_System_Use_Field (VOLUME *p_volume, directory_record *p_dir,
  83.               char *p_name, char *p_buf, int p_buf_len,
  84.               int p_index)
  85. {
  86.   int system_use_pos;
  87.   int slen, len;
  88.   unsigned long length = p_dir->length;
  89.   unsigned char *buf = (unsigned char *) p_dir;
  90.  
  91.   system_use_pos = 33 + p_dir->file_id_length;
  92.   if (system_use_pos & 1)
  93.     system_use_pos++;
  94.   system_use_pos += VOL(p_volume,skip);
  95.  
  96.   /* the system use field must be at least 4 bytes long */
  97.   while (system_use_pos + 3 < length) {
  98.     slen = buf[system_use_pos+2];
  99.     if (buf[system_use_pos] == p_name[0] &&
  100.         buf[system_use_pos+1] == p_name[1]) {
  101.       if (p_index)
  102.         p_index--;
  103.       else {
  104.         len = (slen < p_buf_len) ? slen : p_buf_len;
  105.         memcpy (p_buf, buf + system_use_pos, len);
  106.         return 1;
  107.       }
  108.     }
  109.     /* look for continuation area: */
  110.     if (buf[system_use_pos] == 'C' &&
  111.         buf[system_use_pos+1] == 'E') {
  112.       unsigned long newloc, offset;
  113.       memcpy (&newloc, buf + system_use_pos + 8, 4);
  114.       memcpy (&offset, buf + system_use_pos + 16, 4);
  115.       memcpy (&length, buf + system_use_pos + 24, 4);
  116.       if (!Read_Sector (p_volume->cd, newloc))
  117.         return 0;
  118.       buf = p_volume->cd->buffer;
  119.       system_use_pos = offset;
  120.       continue;
  121.     }
  122.     
  123.     /* look for system use field terminator: */
  124.     if (buf[system_use_pos] == 'S' &&
  125.         buf[system_use_pos+1] == 'T')
  126.       return 0;
  127.  
  128.     system_use_pos += slen;
  129.   }
  130.   return 0;
  131. }
  132.  
  133. /* Determines the Rock Ridge file name of the CDROM object p_obj.
  134.  * The file name will be stored in the buffer p_buf (with length p_buf_len).
  135.  * The file name will NOT be null-terminated. The number of characters in
  136.  * the file name is returned. If there is no Rock Ridge file name for
  137.  * p_obj, then -1 is returned.
  138.  */
  139.  
  140. int Get_RR_File_Name (VOLUME *p_volume, directory_record *p_dir,
  141.               char *p_buf, int p_buf_len)
  142. {
  143.   struct nm_system_use_field {
  144.     char      id[2];
  145.     unsigned char length;
  146.     unsigned char version;
  147.     unsigned char flags;
  148.     char          name[210];
  149.   } nm;
  150.   int len, slen;
  151.   int index = 0;
  152.   int total = 0;
  153.  
  154.   for (;;) {
  155.     if (!Get_System_Use_Field (p_volume, p_dir, "NM",
  156.                      (char *) &nm, sizeof (nm), index))
  157.       return -1;
  158.  
  159.     slen = nm.length-5;
  160.     len = (p_buf_len < slen) ? p_buf_len : slen;
  161.     if (len)
  162.       memcpy (p_buf, nm.name, len);
  163.  
  164.     total += len;
  165.     if (!(nm.flags & 1))
  166.       return total;
  167.  
  168.     p_buf += len;
  169.     p_buf_len -= len;
  170.     index++;
  171.   }
  172. }
  173.  
  174. /* Returns 1 if the PX system use field indicates a symbolic link.
  175.  */
  176.  
  177. int Is_A_Symbolic_Link (VOLUME *p_volume, directory_record *p_dir)
  178. {
  179.   struct px_system_use_field {
  180.     char      id[2];
  181.     unsigned char length;
  182.     unsigned char version;
  183.     unsigned long mode_i;
  184.     unsigned long mode_m;
  185.     unsigned long links_i;
  186.     unsigned long links_m;
  187.     unsigned long user_id_i;
  188.     unsigned long user_id_m;
  189.     unsigned long group_id_i;
  190.     unsigned long group_id_m;
  191.   } px;
  192.  
  193.   if (!Get_System_Use_Field (p_volume, p_dir, "PX", (char *) &px, sizeof (px), 0))
  194.     return 0;
  195.  
  196.   /* 0120000 is the POSIX code for symbolic links:
  197.    */
  198.   return (px.mode_m & 0770000) == 0120000;
  199. }
  200.  
  201. /* Read content of SL system use field.
  202.  * A full path name (starting with ":" or "sys:") will always be returned.
  203.  */
  204.  
  205. t_bool Get_Link_Name (CDROM_OBJ *p_obj, char *p_buf, int p_buf_len)
  206. {
  207.   unsigned char buf[256];
  208.   char out[530];
  209.   int index = 0;
  210.   int len;
  211.   int offs;
  212.   char c;
  213.  
  214.   out[0] = 0;
  215.   for (;; ) {
  216.     if (!Get_System_Use_Field (p_obj->volume, OBJ(p_obj,dir), "SL", (char *) buf,
  217.                      sizeof (buf), index)) {
  218.       return (index == 0) ? 0 : 1;
  219.     }
  220.  
  221.     offs = 5;
  222.     for (;;) {
  223.  
  224.       if (strlen (out) > 256)
  225.         return 0;
  226.  
  227.       if (index == 0 && offs == 5) {
  228.         /* handle the first component record: */
  229.  
  230.         if (buf[5] & 4) /* parent directory */ {
  231.           CDROM_OBJ *parent1 = Find_Parent (p_obj);
  232.       CDROM_OBJ *parent2;
  233.       char fullpath[256];
  234.       if (!parent1)
  235.         return 0;
  236.           parent2 = Find_Parent (parent1);
  237.       if (!parent2)
  238.         return 0;
  239.       if (!Full_Path_Name (parent2, fullpath, sizeof (fullpath)))
  240.         return 0;
  241.       Close_Object (parent1);
  242.       Close_Object (parent2);
  243.       strcat (out, fullpath);
  244.       if (out[1] != 0)
  245.         strcat (out, "/");
  246.         } else if (buf[5] & 8) /* root */
  247.           strcat (out, "sys:");
  248.         else if (buf[5] & 16) /* volume root */
  249.           strcat (out, ":");
  250.         else { /* current directory */
  251.           CDROM_OBJ *parent = Find_Parent (p_obj);
  252.       char fullpath[256];
  253.       if (!parent)
  254.         return 0;
  255.       if (!Full_Path_Name (parent, fullpath, sizeof (fullpath)))
  256.         return 0;
  257.       Close_Object (parent);
  258.       strcat (out, fullpath);
  259.       if (out[1] != 0)
  260.         strcat (out, "/");
  261.         }
  262.       }
  263.  
  264.       if (out[0] && (c = out[strlen(out)-1]) != ':' && c != '/')
  265.         strcat (out, "/");
  266.  
  267.       if (buf[offs] & 32) /* host name */
  268.         strcat (out, "AMIGA");
  269.  
  270.       len = strlen (out);
  271.       memcpy (out + len, buf + offs + 2, buf[offs+1]);
  272.       out[len + buf[offs+1]] = 0;
  273.  
  274.       offs += 2 + buf[offs+1];
  275.       if (offs >= buf[2])
  276.         break;
  277.     }
  278.     if (!(buf[4] & 1)) /* continue flag */
  279.       break;
  280.     index++;
  281.   }
  282.   
  283.   strncpy (p_buf, out, p_buf_len - 1);
  284.   p_buf[p_buf_len-1] = 0;
  285.   return 1;
  286. }
  287.  
  288. /* Check whether a system use field is present: */
  289.  
  290. int Has_System_Use_Field (VOLUME *p_volume, directory_record *p_dir,
  291.               char *p_name)
  292. {
  293.   return Get_System_Use_Field (p_volume, p_dir, p_name, NULL, 0, 0);
  294. }
  295.  
  296. /* Return content of "CL" system use field, or -1, if no such system use field
  297.  * is present.
  298.  */
  299.  
  300. long RR_Child_Link (VOLUME *p_volume, directory_record *p_dir)
  301. {
  302.   struct cl {
  303.     char        name[2];
  304.     char        length[1];
  305.     char        version[1];
  306.     long    pos_i;
  307.     long    pos_m;
  308.   } buf;
  309.   if (!Get_System_Use_Field (p_volume, p_dir, "CL", (char*) &buf, sizeof (buf), 0))
  310.     return -1;
  311.   else
  312.     return buf.pos_m;
  313. }
  314.  
  315. /* Return content of "PL" system use field, or -1, if no such system use field
  316.  * is present.
  317.  */
  318.  
  319. long RR_Parent_Link (VOLUME *p_volume, directory_record *p_dir)
  320. {
  321.   struct pl {
  322.     char        name[2];
  323.     char        length[1];
  324.     char        version[1];
  325.     long    pos_i;
  326.     long    pos_m;
  327.   } buf;
  328.   if (!Get_System_Use_Field (p_volume, p_dir, "PL", (char*) &buf, sizeof (buf), 0))
  329.     return -1;
  330.   else
  331.     return buf.pos_m;
  332. }
  333.  
  334.  
  335.